﻿using Microsoft.VisualStudio.Modeling;
using System.Collections.Generic;
using System.Diagnostics;

namespace Project.Co_DataTransformationPrototype
{
    public static partial class Operators
    {
        private static readonly string strMoveTransactionKey = "MoveOp_Trans_Key";
        private static readonly string strMergeTransactionKey = "MergeOp_Trans_Key";
        private static readonly string strMergeAttributeTransactionKey = "MergeOpAttribute_Trans_Key";
        private static readonly string strSplitTransactionKey = "SplitOp_Trans_Key";
        private static readonly string strSetPrimaryKeyTransactionKey = "SetPrimaryKeyAttrib_Trans_Key";
        private static readonly string strSetForeignKeyTransactionKey = "SetForeignKeyAttrib_Trans_Key";
        private static readonly string strEntityOldNameTransactionKey = "ResetForeignKeyTableName_Trans_Key";
        private static readonly string strAttributeOldNameTransactionKey = "ResetForeignKeyAttributeName_Trans_Key";

        /// <summary>
        /// Initialize the operator composition by setting its store value
        /// </summary>
        /// <param name="store"></param>
        /// <returns></returns>
        public static Operator Define(Store store)
        {
            return new Operator(store);
        }

        #region Transaction key-value properties
        /// <summary>
        /// Property which returns the move-operator transaction key-value
        /// </summary>
        public static string GetMoveOpTransactionKey
        {
            get { return strMoveTransactionKey; }
        }

        /// <summary>
        /// Property which returns the split-operator transaction key-value
        /// </summary>
        public static string GetSplitOpTransactionKey
        {
            get { return strSplitTransactionKey; }
        }

        /// <summary>
        /// Property which returns the merge-operator transaction key-value
        /// </summary>
        public static string GetMergeOpTransactionKey
        {
            get { return strMergeTransactionKey; }
        }

        public static string GetMergeOpAttributeTransactionKey
        {
            get { return strMergeAttributeTransactionKey; }
        }

        public static string GetPrimaryKeyRefTransactionKey
        {
            get { return strSetPrimaryKeyTransactionKey; }
        }

        public static string GetFKEntityOldNameTransactionKey
        {
            get { return strEntityOldNameTransactionKey; }
        }

        public static string GetFKAttributeOldNameTransactionKey
        {
            get { return strAttributeOldNameTransactionKey; }
        }

        public static string GetForeignKeyRefTransactionKey
        {
            get { return strSetForeignKeyTransactionKey; }
        }
        #endregion
        
        /// <summary>
        /// Class containing all of the operator implementations
        /// </summary>
        public partial class Operator
        {
            private Store opStore;

            public Operator(Store store)
            {
                Debug.Assert(store != null);
                this.opStore = store;
            }

            public Entity getEntity(System.Guid entityID)
            {
                return opStore.ElementDirectory.FindElement(entityID) as Entity;
            }
        }
    }

    /// <summary>
    /// A container for properties that are use to create an entity object programmatically
    /// </summary>
    public struct EntityInfo
    {
        public ModelRoot modelRoot;
        public string name;
        public bool isImported;
        public IList<AttributeInfo> attributeList;

        public EntityInfo(ModelRoot modelRoot, string name, bool isImported, IList<AttributeInfo> attributeList = null)
        {
            this.modelRoot = modelRoot;
            this.name = name;
            this.isImported = isImported;

            if (attributeList == null)
                this.attributeList = new List<AttributeInfo>();
            else
                this.attributeList = attributeList;
        }
    }

    /// <summary>
    /// A container for properties that are use to create an attribute object programmatically
    /// </summary>
    public struct AttributeInfo
    {
        public string name;
        public System.Data.SqlDbType type;
        public string typeDescription;
        public Entity parentEntity;
        public System.Guid referencedEntity;
        public bool isForeignKey;
        public bool isPrimaryKey;

        public AttributeInfo(string attributeName, System.Data.SqlDbType type, string typeDescription, Entity parentEntity, System.Guid referencedEntityID, bool isPrimaryKey =false, bool isForeignKey = false)
        {
            this.name = attributeName;
            this.type = type;
            this.typeDescription = typeDescription;
            this.parentEntity = parentEntity;
            this.referencedEntity = referencedEntityID;
            this.isPrimaryKey = isPrimaryKey;
            this.isForeignKey = isForeignKey;
        }
    }

    /// <summary>
    /// A container for properties that are use to create an connector object programmatically
    /// </summary>
    public struct ConnectorInfo
    {
        public Entity target;
        public Entity source;
        public EntityAttribute attributeInTarget;
        /// <summary>
        /// Key attribute in source entity
        /// </summary>
        public string nameAttributeInSource;
        /// <summary>
        /// Key attribute in target entity
        /// </summary>
        public string nameAttributeInTarget;

        public ConnectorInfo(Entity source, Entity target, string nameAttributeInSource, string nameAttributeInTarget, EntityAttribute attributeInTarget, bool isPrimaryKey, bool isForeignKey)
        {
            this.source = source;
            this.target = target;
            this.nameAttributeInSource = nameAttributeInSource;
            this.nameAttributeInTarget = nameAttributeInTarget;
            this.attributeInTarget = attributeInTarget;
            if (isPrimaryKey)
                this.attributeInTarget.isPrimaryKey = true;
            if (isForeignKey)
                this.attributeInTarget.isForeignKey = true;
        }
    }

}
